package com.hk.admin.module.system.service;

import com.hk.admin.common.constant.GlobalConstants;
import com.hk.admin.common.constant.GlobalEnum;
import com.hk.admin.common.base.dto.message.Message;
import com.hk.admin.common.dto.system.menu.MenuDTO;
import com.hk.admin.common.model.system.MenuModel;
import com.hk.admin.common.model.system.RoleModel;
import com.hk.admin.common.model.system.UserModel;
import com.hk.admin.common.base.service.BaseService;
import com.hk.admin.module.system.dao.MenuRepository;
import com.hk.admin.module.system.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class MenuService extends BaseService {

    @Autowired
    private MenuRepository menuRepository;
    @Autowired
    private UserRepository userRepository;

    /**
     * 查询所有
     */
    public ResponseEntity<Message> list() {
        List<MenuModel> menuList = menuRepository.findByDeletedOrderByRank(GlobalEnum.DELETED.NO.getKey());
        // 顶级菜单
        List<MenuModel> firstMenuList = getFirstMenuModels(menuList);
        // 排序菜单
        List<MenuModel> sortedMenuList = getSortedMenuModels(menuList, firstMenuList);
        // 返回DTO
        List<MenuDTO> menuDTOList = menuModelToDTO(sortedMenuList);
        return success(menuDTOList);
    }

    /**
     * 返回DTO对象
     */
    private List<MenuDTO> menuModelToDTO(List<MenuModel> sortedMenuList) {
        List<MenuDTO> menuDTOList = new ArrayList<>();
        sortedMenuList.forEach(menuModel -> {
            MenuDTO menuDTO = new MenuDTO(menuModel);
            menuDTOList.add(menuDTO);
        });
        return menuDTOList;
    }

    /**
     * 排序菜单
     */
    private List<MenuModel> getSortedMenuModels(List<MenuModel> menuList, List<MenuModel> firstMenuList) {
        List<MenuModel> sortedMenuList = new ArrayList<>();
        firstMenuList.forEach(menuModel -> {
            sortedMenuList.add(menuModel);
            List<MenuModel> tempList = new ArrayList<>();
            int index = 0; // 菜单深度
            getAllChildrenMenu(tempList, menuList, menuModel, index);
            sortedMenuList.addAll(tempList);
        });
        return sortedMenuList;
    }

    /**
     * 最顶级的菜单
     */
    private List<MenuModel> getFirstMenuModels(List<MenuModel> menuList) {
        List<MenuModel> firstMenuList = new ArrayList<>();
        // 排序
        for (int i = 0; i < menuList.size(); i++) {
            if (menuList.get(i).getPid() == null) {
                firstMenuList.add(menuList.get(i));
                menuList.remove(i);
                i--;
            }
        }
        return firstMenuList;
    }

    /**
     * 递归出所有的下级菜单
     */
    private void getAllChildrenMenu(List<MenuModel> tempList, List<MenuModel> menuList, MenuModel menuModel, int depth) {
        for (int i = 0; i < menuList.size(); i++) {
            if (menuModel.getId().equals(menuList.get(i).getPid())) {
                MenuModel temp = menuList.get(i);
                temp.addMenuMark(depth);
                tempList.add(temp);
                menuList.remove(i);
                i--;
                getAllChildrenMenu(tempList, menuList, temp, depth + 1);
            }
        }
    }


    /**
     * 查询一个
     */
    public ResponseEntity<Message> query(Long id) {
        MenuModel model = menuRepository.findOne(id);
        if (model == null) {
            return idError();
        }
        MenuDTO menuDTO = new MenuDTO(model);
        return success(menuDTO);
    }

    /**
     * 保存
     */
    public ResponseEntity<Message> save(MenuDTO dto) {
        MenuModel model = new MenuModel(dto);
        menuRepository.save(model);
        return saveSuccess();
    }

    /**
     * 删除成功
     */
    @Transactional
    public ResponseEntity<Message> delete(Long id) {
        MenuModel model = menuRepository.findOne(id);
        if (model == null) {
            return idError();
        }
        model.delete();
        menuRepository.save(model);
        menuRepository.deleteChildrenMenu(model.getId(), GlobalEnum.DELETED.YES.getKey());
        return deleteSuccess();
    }

    /**
     * 当前登陆人的菜单
     */
    public ResponseEntity<Message> getMenuList(String phoneNumber) {
        UserModel model = userRepository.findByPhoneNumberAndDeleted(phoneNumber, GlobalEnum.DELETED.NO.getKey());
        List<MenuModel> menuList = getMenuModels(model);
        // 返回DTO
        List<MenuDTO> menuDTOList = menuModelToDTO(menuList);
        return success(menuDTOList);
    }

    /**
     * 当前登陆人的菜单
     */
    public List<String> getMenuActionList(UserModel model) {
        List<MenuModel> menuList = getMenuModels(model);
        Set<String> menuUrls = new HashSet<>();
        menuList.forEach(e -> {
            setActions(menuUrls, e.getActions());
        });
        return new ArrayList<>(menuUrls);
    }

    private void setActions(Set<String> menuUrls, String actions) {
        if (actions != null) {
            String[] actionArray = actions.split(GlobalConstants.COMMA);
            for (String action : actionArray) {
                menuUrls.add(action);
            }
        }
    }

    /**
     * 当前登录人的有权限的菜单
     */
    private List<MenuModel> getMenuModels(UserModel model) {
        List<MenuModel> menuList;
        // 如果是超级管理员
        if (model.iAmASuperAdmin()) {
            menuList = menuRepository.findByDeletedOrderByRank(GlobalEnum.DELETED.NO.getKey());
        } else {
            List<MenuModel> menuListTemp = getMenusByRoles(model.getRoles());
            List<MenuModel> parentMenuList = getParentMenus(menuListTemp);

            Set<MenuModel> menus = new HashSet<>();
            menus.addAll(menuListTemp);
            menus.addAll(parentMenuList);
            menuList = new ArrayList<>(menus);
        }
        return menuList;
    }

    /**
     * 用户关联的权限菜单
     */
    private List<MenuModel> getMenusByRoles(List<RoleModel> roles) {
        Set<MenuModel> menus = new HashSet<>();
        roles.forEach(e -> {
            if (!e.alreadyDeleted()) {
                menus.addAll(e.getMenus());
            }
        });
        List<MenuModel> menuList = new ArrayList<>();
        menuList.addAll(menus);
        return menuList;
    }

    /**
     * 上级菜单
     */
    private List<MenuModel> getParentMenus(List<MenuModel> menuList) {
        Set<String> menuIds = new HashSet<>();
        menuList.forEach(e -> {
            String[] tempPids = e.getPids().split(GlobalConstants.COMMA);
            menuIds.addAll(Arrays.asList(tempPids));
        });
        List<Long> parentIds = new ArrayList<>();
        menuIds.forEach(e -> {
            parentIds.add(Long.parseLong(e));
        });
        return menuRepository.findByIdIn(parentIds);
    }


}
